﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using MvcRags.Core;
using System.Web.Mvc.Html;

namespace MvcRags.Filtering
{
    public static class FilterHelper
    {
        private const string FilterSearchField = "mvcr_searchField";
        private const string FilterSearchValue = "mvcr_searchValue";

        public static IQueryable<T> Filter<T>(this Controller controller, IQueryable<T> entries, FilterMode mode)
        {
            Func<string, string, IQueryable<T>> filter;
            switch (mode)
            {
                case FilterMode.Contains:
                    filter = (field, value) => (IQueryable<T>) entries.WhereContains(field, value);
                    break;
                case FilterMode.StartsWith:
                    filter = (field, value) => (IQueryable<T>)entries.WhereStartsWith(field, value);
                    break;
                case FilterMode.EndsWith:
                    filter = (field, value) => (IQueryable<T>)entries.WhereEndsWith(field, value);
                    break;
                default:
                    throw new ArgumentOutOfRangeException("mode");
            }
            return Filter(controller, entries, filter);
        }

        public static IQueryable<T> Filter<T>(this Controller controller, IQueryable<T> entries)
        {
            return Filter(controller, entries,
                             (field, value) => (IQueryable<T>) entries.WhereContains(field, value));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="controller"></param>
        /// <param name="entries"></param>
        /// <param name="filterExpression">First Arg is the selected Field, second is the Value</param>
        /// <returns></returns>
        public static IQueryable<T> Filter<T>(this Controller controller, IQueryable<T> entries, Func<string, string, IQueryable<T>> filterExpression )
        {
            string searchField = controller.Request.Params[FilterSearchField];
            string searchValue = controller.Request.Params[FilterSearchValue];
                
            if (!String.IsNullOrWhiteSpace(searchField) && !String.IsNullOrWhiteSpace(searchValue))
            {
                controller.ViewBag.SearchField = searchField;
                controller.ViewBag.SearchValue = searchValue;
                return filterExpression(searchField, searchValue);
                
            }

            return entries;  
        }

        public static SelectList FilterSelectListForModel<TModel>(this HtmlHelper<IEnumerable<TModel>> htmlHelper)
        {
            List<PropertyInfo> props = typeof(TModel).GetProperties().Where(prop => prop.PropertyType == typeof(string)).ToList();
            string currentField = htmlHelper.ViewContext.HttpContext.Request.Params[FilterSearchField];
            if (currentField == null) currentField = props.First().Name;
            return new SelectList(props, "Name", "Name", currentField);
        }

        public static MvcForm BeginFilterForm<TModel>(this HtmlHelper<IEnumerable<TModel>> htmlHelper,
                                                      object htmlAttributes = null)
        {
            string actionName = (string)htmlHelper.ViewContext.Controller.ValueProvider.GetValue("action").RawValue;
            string controllerName = (string)htmlHelper.ViewContext.Controller.ValueProvider.GetValue("controller").RawValue;

            return htmlHelper.BeginForm(actionName, controllerName, FormMethod.Get, htmlAttributes);
        }

        public static MvcHtmlString FilterDropDownForModel<TModel>(this HtmlHelper<IEnumerable<TModel>> htmlHelper, object htmlAttributes = null)
        {
            SelectList selectList = FilterSelectListForModel(htmlHelper);
            return htmlHelper.DropDownList(FilterSearchField, selectList, htmlAttributes);
        }

        public static MvcHtmlString FilterTextboxForModel<TModel>(this HtmlHelper<IEnumerable<TModel>> htmlHelper,
                                                                  object htmlAttributes = null)
        {
            string currentValue = htmlHelper.ViewContext.HttpContext.Request.Params[FilterSearchValue];
            return htmlHelper.TextBox(FilterSearchValue, currentValue, htmlAttributes);
        }
    }
}